#ifndef __MGGS_EQS__
#define __MGGS_EQS__

#include <iostream>
using namespace std;

template <typename T>
class EquationSolver{
protected:
  T (*pf)(T);
  T (*pdf)(T);
  int max_iter;
  T tol;
public:
  typedef T (*F)(T);
  EquationSolver();
  EquationSolver(const int _max_iter, const T _tol, T (*_pf)(T));
  EquationSolver(const int _max_iter, const T _tol, T (*_pf)(T), T (*_pdf)(T));
  ~EquationSolver();
  void set_max_iter(const int _max_iter);
  int get_max_iter() const;
  void set_tol(const T _tol);
  T get_tol() const;
  void set_function(T (*_pf)(T));
  void set_dfunction(T (*_pdf)(T));
  void set_allfunction(T (*_pf)(T), T (*_pdf)(T));
  F get_function() const;
  F get_dfunction() const;
  virtual T solve() = 0; 
};

template <typename T>
EquationSolver<T>::EquationSolver(){
  pf = NULL;
  pdf = NULL;
  max_iter = 0;
  tol = 0;
}


template <typename T>
EquationSolver<T>::~EquationSolver(){}


template <typename T>
EquationSolver<T>::EquationSolver(const int _max_iter, const T _tol, T (*_pf)(T)){
  max_iter = _max_iter;
  tol = _tol;
  set_function(_pf);
}


template <typename T>
EquationSolver<T>::EquationSolver(const int _max_iter, const T _tol, T (*_pf)(T), T (*_pdf)(T)){
  max_iter = _max_iter;
  tol = _tol;
  set_allfunction(_pf,_pdf);
}


template <typename T>
void EquationSolver<T>::set_max_iter(const int _max_iter){
  max_iter = _max_iter;
}

template <typename T>
int EquationSolver<T>::get_max_iter() const{
  return max_iter;
}

template <typename T>
void EquationSolver<T>::set_tol(const T _tol){
  tol = _tol;
}

template <typename T>
T EquationSolver<T>::get_tol() const{
  return tol;
}


template <typename T>
void EquationSolver<T>::set_function(T (*_pf)(T)){
  pf = _pf;
}

template <typename T>
void EquationSolver<T>::set_dfunction(T (*_pdf)(T)){
  pdf = _pdf;
}

template <typename T>
void EquationSolver<T>::set_allfunction(T (*_pf)(T), T (*_pdf)(T)){
  pf = _pf;
  pdf = _pdf;
}

template <typename T>
typename EquationSolver<T>::F EquationSolver<T>::get_function() const{
  return pf;
}

template <typename T>
typename EquationSolver<T>::F EquationSolver<T>::get_dfunction() const{
  return pdf;
}


#else
// DO NOTHING.
#endif
